﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.ServiceModel;

using System.ComponentModel;

using Newtonsoft.Json;

namespace MSAP.ObjectsStore
{
    public class JSONRecordSetProvider<TRECORD> :   IRecordSet<TRECORD>
                                                    where TRECORD : RecordBase<TRECORD>, new()
    {
        private JSONRecordSetProvider()
        {
            // USE CreateRecordSetProvider for create instance
        }

        public static IRecordSet<TRECORD> CreateRecordSetProvider()
        {
            // Implementation d'un singleton
            if (m_Instance == null)
                m_Instance = new JSONRecordSetProvider<TRECORD>();
            return m_Instance;
        }

        public TRECORD CreateRecord()
        {
            TRECORD r = new TRECORD();
            r.Oid = Guid.NewGuid();
            r.RecordState = eRecordState.Created;
            r.RecordStore = eRecordStore.Memory;
            AddRecord(r);
            return r;
        }

        public TRECORD LoadRecord(Guid _Oid)
        {
            // Dans le provider SOAP toutes les données sont charger en memoire 
            // Donc une demande de chargement specifique n'a pas de sens
            TRECORD rec = GetRecord(_Oid);
            return rec;
        }

        public void AddRecord(TRECORD theRecord)
        {
            // Si l'objet n'est pas deja dans le cache, on le met dedans
            if (GetRecord(theRecord.Oid) == null)
                Records.Add(theRecord);
        }

        public void DeleteRecord(Guid Oid)
        {
            TRECORD theRecord = GetRecord(Oid);
            if (theRecord != null)
            {
                theRecord.Delete();
                Records.Remove(theRecord);
            }
        }

        public TRECORD GetRecord(Guid Oid)
        {
            foreach (TRECORD theRecord in Records)
            {
                if (theRecord.Oid == Oid)
                    return theRecord;
            }

            return default(TRECORD);
        }

        public void Save(string sFileName)
        {
            Serializer(sFileName);
        }

        public void Save(string sFileName, List<Guid> lstGuid)
        {
            Serializer(sFileName);
        }

        public void Load(string sFileName)
        {
            UnSerializer(sFileName);
        }

        public ObservableCollection<TRECORD> Records 
        {
            get
            {
                if (m_Records == null)
                    m_Records = new ObservableCollection<TRECORD>();
                return m_Records;
            }
            private set 
            {
                m_Records = value;
            }
        }

        protected void Serializer(string sFileName)
        {
            foreach (TRECORD r in Records)
                r.Save();

            JsonSerializer serializer = new JsonSerializer();
            using (StreamWriter sw = new StreamWriter(sFileName))
            {
                using (JsonWriter writer = new JsonTextWriter(sw))
                {
                    serializer.Serialize(writer, Records);
                }
            }

        }

        protected void UnSerializer(string sFileName)
        {
            try 
            {
                JsonSerializer serializer = new JsonSerializer();
                using (StreamReader sw = new StreamReader(sFileName))
                {
                    using (JsonReader reader = new JsonTextReader(sw))
                    {
                        serializer.Deserialize(reader, typeof(ObservableCollection<TRECORD>));
                    }
                }

                foreach (TRECORD r in Records)
                    r.Load();
            }
            catch(Exception)
            {
            }
        }

        #region INotifyPropertyChanged Members
        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged(string propertyName)
        {
            System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
            if ((propertyChanged != null))
            {
                propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion

        #region Fields
        private ObservableCollection<TRECORD> m_Records;
        public static IRecordSet<TRECORD> m_Instance = null;
        #endregion
    }
}
